<?php

/*
 * Загрузчик файлов
 */

namespace T4\FS;

use T4\Exception;

class Uploader {
    
    protected $basepath;
    protected $fieldname;
    protected $mode;
    
    /**
     * Модель, для которой работает аплоадер
     * @var \T4\Model Ссылка на переменную-модель 
     */
    protected $model;

    public function __construct($mode='keep') {
        $this->mode = $mode;
        $this->setUploadPath();   
    }
    
    public function setUploadPath($path='') {
        
        $basepath = \ROOT_PATH . '/public/' . $path;
        
        if ( !file_exists($basepath)  && !mkdir($basepath, 0777, true) ) {
            throw new Exception('Путь ' . $basepath . ' не существует и не может быть создан!');
        }
        
        if ( !is_writeable($basepath) )
            throw new Exception('Нет прав на запись по пути ' . $basepath . ' !');
        
        $this->basepath = $path;
        
    }
    
    public function setModel( \T4\Model $model) {
        $this->model = $model;
    }
    
    protected function getPersistentFileName() {
        return basename($_FILES[$this->fieldname]['name']);
    }
    
    protected function rename($filename) {
        
        $path = pathinfo(\ROOT_PATH . '/public/' . $this->basepath . '/' . $filename);
        
        $next = 0;
        foreach ( glob( $path['dirname'] . '/' . $path['filename'] . '*' . (!empty($path['extension']) ? '.'.$path['extension'] : '') ) as $file) {
            $next++;
        }
        
        return preg_replace("/(" . $path['filename'] . ")/", "$1_" . $next, $filename);
        
    }


    public function __invoke($fieldname) {
        
        $this->fieldname = $fieldname;
        
        /*
         * Есть модель
         * форма построена по модели
         * и выбран чекбокс "удалить" этот файл
         * Удаляем, дальнейшая обработка смысла не имеет
         */
        if ( isset($_REQUEST['delete_' . $this->fieldname]) ) {
            if ( !is_null($this->model) ) {
                $fullFileName = \ROOT_PATH . '/public/' . $this->model->{$this->fieldname};
            } else {
                $fullFileName = \ROOT_PATH . '/public/' . $_REQUEST['delete_' . $this->fieldname];
            }
            @unlink($fullFileName);
            foreach ( glob($fullFileName . '*.preview*') as $previewFileName ) {
                @unlink($previewFileName);
            }
            return null;
        }
        
        if ( empty($_FILES[$this->fieldname]['name']) )
            return is_null($this->model) ? null : $this->model->{$this->fieldname};
        
        if ( UPLOAD_ERR_NO_FILE == $_FILES[$this->fieldname]['error'] )
            throw new Exception('Файл (поле ' . $this->fieldname . ') не загружен на сервер');
        
        if ( UPLOAD_ERR_OK != $_FILES[$this->fieldname]['error'] )
            throw new Exception('Файл ' . $_FILES[$this->fieldname]['name'] . ' не может быть загружен. Код ошибки ' . $_FILES[$this->fieldname]['error']);
        
        $filename = $this->getPersistentFileName();
        $fullFileName = \ROOT_PATH . '/public/' . $this->basepath . '/' . $filename;
        
        if ( $this->mode == 'keep' && file_exists($fullFileName) ) {
            $filename = $this->rename($filename);
            $fullFileName = \ROOT_PATH . '/public/' . $this->basepath . '/' . $filename;
        }
        
        /*
         * Файл успешно загружен и перемещен в хранилище
         */
        if ( @move_uploaded_file($_FILES[$this->fieldname]['tmp_name'], $fullFileName) ) {
            
            /*
             * Если есть связь с моделью, то хорошо бы удалить файлы, ранее в ней сохраненные
             */
            if ( !is_null($this->model) ) {
                $oldFileName = \ROOT_PATH . '/public/' . $this->model->{$this->fieldname};
                @unlink($oldFileName);
                foreach ( glob($oldFileName . '*.preview*') as $previewFileName ) {
                    @unlink($previewFileName);
                }
            }
            
            return $this->basepath . '/' . $filename;
            
        } else {
            throw new Exception('Ошибка при перемещении файла в хранилище');
        }
        
    }
    
}
